#ifndef _TSS_WRITER_H_
#define _TSS_WRITER_H_

#include "polsys_mcu.h"

// 事件
typedef enum _tw_ev
{
    TW_EV_WR_OK,            // 写入（输出参数）成功
    TW_EV_WR_FAIL,          // 写入失败，通过 TssWriter_GetErrCode() 获取错误代码。
    TW_EV_RD_OK,            // 读取（输出参数）成功
    TW_EV_RD_FAIL,          // 读取失败
    TW_EV_RD_NONE,          // 未读取到输出参数数据（从机是不支持的输出模式）
    TW_EV_PLUG_IN,          // 有设备接入（此时还未识别）
    TW_EV_SLOW_PORT,        // 正在通过慢速接口通信，需要更长的时间（1秒左右)才能出结果
    TW_EV_IDENTIFIED,       // 已识别接入的设备（正品）
    TW_EV_INFO_UPDATE,      // 产品信息有更新,可通过 TW_GetDevInfo 获取设备信息
    TW_EV_UNKNOW_DEV,       // 接入了无法识别的设备（仿品）
    TW_EV_PLUG_OUT          // 断开连接，包括无法识别的设备被移除
}tw_ev_t;

// 状态
typedef enum _tw_status
{
    TW_ST_ERROR,
    TW_ST_NO_CON = 1,       // 未连接，正在检测接入
    TW_ST_CON,              // 有设备接入，等待尝试通信

    TW_ST_IDFING,           // 正在识别设备，正在等待识别包发送与接收完毕
    TW_ST_FAKE,             // 接口上连接的是仿品
    TW_ST_GENUINE,          // 接口上连接的是正品，通信就绪状态
    TW_ST_GENUINE_TO,       // 接口上连接的是正品，通信已断开（产品还是接上的），需要重新发送识别包建立链接
    TW_ST_RE_IDFING_WR,     // 重新发送识别包进行同步。写入前发送识别包进行同步。
    TW_ST_RE_IDFING_RD,     // 重新发送识别包进行同步。读取前发送识别包进行同步。
    TW_ST_WRITE_WAIT,       // 写入前的等待，同步后从机需要时间准备接收下一包数据。
    TW_ST_READ_WAIT,        // 读取前的等待
    TW_ST_GET_BASIC_WAIT,   // 读取基础信息前的等待
    TW_ST_WRITING,          // 正在写入 SetParam(0X23)
    TW_ST_READING,          // 正在读取 GetParam(0X22)
    TW_ST_GETTING_BASIC,    // 正在获取基础信息（工程机才有）

    TW_ST_MEASURING,        // 正在测量（产品电池电压、发热丝电阻）
    TW_ST_END
}tw_status_t;

// 设备类型
typedef enum _dev_type
{
    DEV_TYPE_IM_BASE = 0x00,    // 反推ADC数据的基础产品（仅支持识别包通信）
    DEV_TYPE_FM_BASE = 0x01,    // 正推ADC数据的基础产品（仅支持识别包通信）
    DEV_TYPE_DEFAULT = 0X30,    // 支持修改参数的默认产品（0.8Ω一体机，数据无校验，长度大端(高字节在前））
    DEV_TYPE_NORMAL  = 0X31,    // 支持修改参数的常规产品（可变基础参数）
    DEV_TYPE_NM_BASE = 0XFF     // 无产品信息的基础产品（仅支持识别包通信，无设备信息，早期的D+通信量产机）
}dev_type_t;

// 产品通信接口
typedef enum _comm_port
{
    COMM_PORT_DP,
    COMM_PORT_VBUS
}comm_port_t;

// 输出模式
typedef enum _output_mode
{
    OUTPUT_MODE_PWM = 0,
    OUTPUT_MODE_VAVG = 1,
    OUTPUT_MODE_VRMS = 2,
    OUTPUT_MODE_POWER = 3,
    OUTPUT_MODE_TEMP = 4
}output_mode_t;

typedef enum _tw_model
{
    TW_MODEL_D8_L3_TS813BB2,
    TW_MODEL_UNKNOW = 0XFF
}tw_model_t;

// 通信参数
typedef struct _com_param_field
{
    u8 ByteFm           :1;     // 0-小端,1-大端
    u8 HasCheckCode     :1;     // 0-无校验,1-有校验
    u8 CheckCodeType    :2;     // 0-和校验,1-CRC16
    u8 Reserved4        :4;
}com_param_field_t;


// 产品的信息, 依据产品类型有些数据可能无效（读取得到错误值），详见通信协议。 （0X30缺失的部分都是默认值）
typedef struct _dev_info
{
    dev_type_t Type;        // 产品类型（系列）
    comm_port_t CommPort;   // 产品通信接口
    // 以下信息仅工程机才有 Type>=0X30
    u16 Timeout;            // 退出通信模式超时ms，退出后需要再次发送识别包（同步包）
    u16 MaxRxLen;           // 最大接收字节数
    union
    {
        u8 ComParam;        // 后续的数据包通信的通信参数
        com_param_field_t ComParam_f;
    };
    tw_model_t Model;               // 产品型号
    output_mode_t SugOutputMode;    // 推荐的输出模式，本设备将按照推荐模式设置
    u16 DesignRes;          // 产品设计发热丝阻值，单位mΩ。（使用此值计算电压有效值）
    // 以下信息量产机(IM_BASE\FM_BASE)在识别包中（BASE产品无此信息），工程机发GetBasic获取(接入产品后自动获取)
    u16 ReportRes;          // 产品汇报的实际发热丝电阻mΩ（精度可能较差，仅用于不良品分析）
    u16 ReportBattVoltage;  // 产品汇报的电池电压 mV (未输出时，优先使用此值计算电量)
    u16 BattLoadVoltage;    // 产品汇报的输出时电池电压mV（结合 ReportRes 可用于分析电芯带载能力）
    // 以下信息是计算得出或者本机测量得出
    u16 MeasuRes;           // 通过D-/CC脚实测的发热丝电阻mΩ（因为是测量的，所以包含了接口和导线电阻）
    u16 MeasuBattVoltage;   // 通过D+脚实测的电池电压mV （仅D+通信的产品可以获取，无 ReportBattVoltage 时使用此值计算电量）
    u8 BattLevel;           // 电量
}tw_dev_info_t;


// 通知TW测量完成
// 在 _TW_StartMeasuring() 之后开始测量产品的电池产压和发热丝电阻，测量完成后需要调用本函数来通知TW。
// load_res：发热丝电阻mΩ
// batt_voltage: 电池电压mV
// 函数内部仅进行变量修改，可在中断中调用。
void TW_EvMeasDone(u16 load_res, u16 batt_voltage);

void TW_Init();

void TW_SetCb(void (*new_cb)(tw_ev_t e));

// 获取当前状态
tw_status_t TW_GetStatus();

// 获取设备信息（指针）
tw_dev_info_t * TW_GetDevInfo();

// 【异步】开始写入输出功率(mW)，固定为10个u16，结果出来之前不可以释放 param 内存。
// 返回值： true-开始写入（不代表写入成功）；false: 状态错误（非TW_ST_GENUINE 或者 TW_ST_GENUINE_TO, 或者接入的是量产机）。
bool TW_StartWrite(u16 * param);

// 【异步】开始读取输出功率(mW)，固定为10个u16，结果出来之前不可以释放 param 内存。
// 返回值： true-开始读取（不代表读取成功）；false: 状态错误（非TW_ST_GENUINE 或者 TW_ST_GENUINE_TO, 或者接入的是量产机）。
bool TW_StartRead(u16 * param);

#endif
